//-------------------------------------------------------------------------------------
// <copyright file="TransportData.cs" company="Microsoft">
//      Copyright (c) 2003 Microsoft Corporation. All rights reserved.
//      THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
//      EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
//      WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <summary>
//      Holds initialization data for a transport, often known as an adapter.
// </summary>  
//-------------------------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.BizTalk2004.Configuration
{
	#region Using directives

	using System;
	using System.Collections;
	using System.Globalization;
	using System.IO;
	using System.Text;
	using System.Xml;

	#endregion

	/// <summary>
	/// Holds initialization data for a transport, often known as an adapter.
	/// </summary>
	/// <remarks>
	/// Classes for more specific adapter types such as <b>HTTP</b> or <b>SOAP</b> may derive from this class
	/// to provide defined properties for each of their transport settings, rather than relying on users to
	/// know the names and types of the transport data properties for that adapter.
	/// </remarks>
	internal class TransportData
	{
		#region Member Variables

		private TransportDataItemCollection items = new TransportDataItemCollection();

		private TransportDataParentType parentType;

		#endregion

		#region Constructors

		/// <summary>
		/// Creates a new transport data instance.
		/// </summary>
		public TransportData()
		{
		}

		/// <summary>
		/// Creates a new transport data instance from a transport XML string.
		/// </summary>
		/// <remarks>
		/// This contructor calls straight through to the 
		/// <see cref="Microsoft.Sdc.Tasks.BizTalk2004.Configuration.TransportData.InitializeFromXml"/> method. Derived
		/// classes should override this method if they want to perform custom initialization for a particular
		/// adapter type.
		/// </remarks>
		public TransportData(string transportXml)
		{
			this.InitializeFromXml(transportXml);
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets the collection of transport data items.
		/// </summary>
		/// <value>
		/// A <see cref="Microsoft.Sdc.Tasks.BizTalk2004.Configuration.TransportDataItemCollection"/>.
		/// </value>
		public TransportDataItemCollection Items
		{
			get
			{
				return this.items;
			}
		}

		/// <summary>
		/// The ParentType of this TransportData object
		/// </summary>
		public TransportDataParentType ParentType
		{
			get {return this.parentType;}
			set {this.parentType = value;}
		}

		#endregion

		#region Methods

		/// <summary>
		/// Gets the XML string representing the transport information.
		/// </summary>
		/// <remarks>
		/// Derived classes can override this method to provide custom XML generation if their XML transport
		/// string is not in the standard format. In this case they should not call this base method implenentation
		/// which will save the transport data in the standard XML format.
		/// </remarks>
		/// <returns>
		/// An XML string representing the transport information.
		/// </returns>
		public virtual string GetTransportXml()
		{
			string transportXml = null;
			if (this.items.Count > 0)
			{
				using (MemoryStream stream = new MemoryStream())
				{
					XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8);
					try
					{
						//write the document into the memory stream
						writer.WriteStartElement("CustomProps");
						foreach (TransportDataItem item in this.items)
						{
							writer.WriteStartElement(item.Name);
							writer.WriteAttributeString("vt", item.TypeCode.ToString(NumberFormatInfo.InvariantInfo));
							if (item.Value != null)
							{
								writer.WriteString(item.ValueString);
							}
							writer.WriteEndElement();
						}
						writer.WriteEndElement();
						writer.Flush();

						//get the data from the stream
						stream.Position = 0L;
						using (StreamReader reader = new StreamReader(stream))
						{
							transportXml = reader.ReadToEnd();
						}
					}
					finally
					{
						//clean up the writer
						if (writer != null)
						{
							writer.Close();
						}
					}
				}
			}
			return transportXml;
		}

		/// <summary>
		/// Loads transport data from the transport XML string.
		/// </summary>
		/// <remarks>
		/// Derived classes can override this method to provide custom initialization if their XML transport
		/// string is not in the standard format. In this case they should not call this base method implenentation
		/// which will load the transport data from the standard format XML.
		/// </remarks>
		/// <param name="transportXml">
		/// The transport XML string to initialize from.
		/// </param>
		protected virtual void InitializeFromXml(string transportXml)
		{
			this.items.Clear();
			XmlDocument document = new XmlDocument();
			document.LoadXml(transportXml);
			foreach (XmlElement element in document.DocumentElement.ChildNodes)
			{
				int typeCode = int.Parse(element.Attributes["vt"].Value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
				object elementValue = (element.IsEmpty) ? null : element.InnerText;
				this.items.Add(new TransportDataItem(element.LocalName, typeCode, elementValue));
			}
		}

		#endregion
	}
}

